﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using Microsoft.SharePoint;

namespace ServBus.ListForm2013.Common.XSNOperator
{
    public class XSNOperator
    {
        protected internal int G_LkpCount;
        protected internal bool G_SaveToLocal;
        public string G_Site_Url;
        protected internal List<XSNFile> G_XSNFiles = new List<XSNFile>();

        protected XSN_DDF G_XSN_DDF;
        public string G_XSN_Url;

        public XSNOperator()
        {
            SListsInfo = new List<XListInfo>();
            MListInfo = new XListInfo();
        }

        //Used for xsn upload to sp folder
        public Guid SiteId { get; set; }
        //Used for xsn upload to sp folder
        public Guid WebId { get; set; }
        //Used for xsn upload to sp folder
        public Guid ListId { get; set; }
        //Used for xsn upload to sp folder
        public SPContentTypeId CTypeId { get; set; }

        public Dictionary<SPContentTypeId, Guid> ScTypeIdSListId { get; set; }

        public string XSNTemplateFolder { get; set; }

        public string SaveFolder { get; set; }

        public XListInfo MListInfo { get; set; }

        public List<XListInfo> SListsInfo { get; set; }

        private void Initial()
        {
            G_SaveToLocal = true;
            SaveFolder = "C:\\TempXsnFiles\\" + Guid.NewGuid();
            Directory.CreateDirectory(SaveFolder);
            //InitialXSNFile
            //rootschema.xsd
            XSN_Rootschema xsnRootschema = new XSN_Rootschema();
            xsnRootschema.Initial(this);
            G_XSNFiles.Add(xsnRootschema);
            //Myschema.xsd
            XSN_Myschema xsnMyschema = new XSN_Myschema();
            xsnMyschema.Initial(this);
            G_XSNFiles.Add(xsnMyschema);
            //Sampledata.xml
            XSN_Sampledata xsnSampledata = new XSN_Sampledata();
            xsnSampledata.Initial(this);
            G_XSNFiles.Add(xsnSampledata);
            //Template.xml
            XSN_Template xsnTemplate = new XSN_Template();
            xsnTemplate.Initial(this);
            G_XSNFiles.Add(xsnTemplate);
            //View.xml
            XSN_View xsnView = new XSN_View();
            xsnView.Initial(this);
            G_XSNFiles.Add(xsnView);
            //Choices.xsd
            XSN_Choices_XSD xsnChoicesXSD = new XSN_Choices_XSD();
            xsnChoicesXSD.Initial(this);
            G_XSNFiles.Add(xsnChoicesXSD);
            //Choices.xml
            XSN_Choices_XML xsnChoicesXML = new XSN_Choices_XML();
            xsnChoicesXML.Initial(this);
            G_XSNFiles.Add(xsnChoicesXML);
            //Manifest.xsf
            XSN_Manifest xsnManifest = new XSN_Manifest();
            xsnManifest.Initial(this);
            G_XSNFiles.Add(xsnManifest);
            XSN_Builtincontrolsschema xsnBuiltincontrolsschema = new XSN_Builtincontrolsschema();
            xsnBuiltincontrolsschema.Initial(this);
            G_XSNFiles.Add(xsnBuiltincontrolsschema);
            //Package.ddf
            G_XSN_DDF = new XSN_DDF();
            G_XSN_DDF.Initial(this);
            //Lookup.xsd
            G_LkpCount = 0;

            #region Initial LookupField

            //Add Lookup field in Main List
            foreach (XFieldInfo mFieldInfo in MListInfo.ContentTypeInfoList[0].FieldInfoList)
            {
                if (mFieldInfo != null)
                {
                    if (mFieldInfo.FieldInfoType == FieldInfoType.LookUp)
                    {
                        G_LkpCount++;
                        LookUpFieldInfo lkpFieldInfo = (LookUpFieldInfo)mFieldInfo;
                        lkpFieldInfo.AppendFieldDefXSD(this);
                    }
                }
            }
            //Add Lookup field in Sub List
            foreach (XListInfo sListInfo in SListsInfo)
            {
                foreach (ContentTypeInfo sCTypeInfo in sListInfo.ContentTypeInfoList)
                {
                    for (int i = 0; i < sCTypeInfo.FieldInfoList.Count; i++)
                    {
                        XFieldInfo sFieldInfo = sCTypeInfo.FieldInfoList[i];
                        if (sFieldInfo != null)
                        {
                            if (sFieldInfo.FieldInfoType == FieldInfoType.LookUp)
                            {
                                LookUpFieldInfo lkpFieldInfo = (LookUpFieldInfo)sFieldInfo;
                                if (lkpFieldInfo.LookupListName != MListInfo.ListTitle)
                                {
                                    G_LkpCount++;
                                    lkpFieldInfo.AppendFieldDefXSD(this);
                                }
                                else
                                {
                                    sCTypeInfo.FieldInfoList.Remove(sFieldInfo);
                                    i--;
                                }
                            }
                        }
                    }
                }
            }

            #endregion
        }

        public bool GenerateXSN()
        {
            bool rStatus;

            try
            {
                Initial();

                //Generate Main List
                foreach (XSNFile xsnFile in G_XSNFiles)
                {
                    if (xsnFile.TemplateName.Equals("view1.xsl") && MListInfo.ContentTypeInfoList[0].HasView)
                    {
                        foreach (XFieldInfo mFieldInfo in MListInfo.ContentTypeInfoList[0].ViewFieldList)
                        {
                            xsnFile.AppendFieldInfoMainDef(mFieldInfo);
                        }
                    }
                    else
                    {
                        foreach (XFieldInfo mFieldInfo in MListInfo.ContentTypeInfoList[0].FieldInfoList)
                        {
                            xsnFile.AppendFieldInfoMainDef(mFieldInfo);
                        }
                    }
                }
                //Generate Sub List
                if (SListsInfo.Count > 0)
                {
                    foreach (XListInfo sListInfo in SListsInfo)
                    {
                        foreach (XSNFile xsnFile in G_XSNFiles)
                        {
                            xsnFile.AppendFieldInfoSubDef(sListInfo);
                        }
                    }
                }

                Package();
                rStatus = true;
            }
            catch (Exception)
            {
                rStatus = false;
            }
            return rStatus;
        }

        private void Package()
        {
            string ddfContent = File.ReadAllText(G_XSN_DDF.SavePath, Encoding.UTF8);
            StringBuilder packageFileNames = new StringBuilder();

            foreach (XSNFile baseXSNFile in G_XSNFiles)
            {
                baseXSNFile.Save();
                packageFileNames.Append(baseXSNFile.TemplateName + "\r\n");
            }

            using (FileStream fs = new FileStream(G_XSN_DDF.SavePath, FileMode.OpenOrCreate, FileAccess.Write))
            {
                StreamWriter sw = new StreamWriter(fs);
                sw.Write(ddfContent + packageFileNames);
                sw.Flush();
            }

            Process proc = new Process
            {
                StartInfo = new ProcessStartInfo(Environment.SystemDirectory + @"\makecab.exe",
                    "/f " + SaveFolder + @"\package.ddf") { WorkingDirectory = SaveFolder }
            };
            proc.Start();
        }



        public bool RefresehXSN(string saveFolder)
        {
            G_SaveToLocal = true;
            SaveFolder = saveFolder;
            XSN_Rootschema xsnRootschema = new XSN_Rootschema();
            xsnRootschema.Initial(this);
            //Myschema.xsd
            XSN_Myschema xsnMyschema = new XSN_Myschema();
            xsnMyschema.Initial(this);

            try
            {
                //Generate Main List
                foreach (XFieldInfo mFieldInfo in MListInfo.ContentTypeInfoList[0].FieldInfoList)
                {
                    xsnMyschema.AppendFieldInfoMainDef(mFieldInfo);
                }
                //Generate Sub List
                if (SListsInfo.Count > 0)
                {
                    foreach (XListInfo sListInfo in SListsInfo)
                    {
                        xsnMyschema.AppendFieldInfoSubDef(sListInfo);
                    }
                }
                xsnRootschema.Save();
                xsnMyschema.Save();

                //package
                G_XSN_DDF = new XSN_DDF();
                G_XSN_DDF.Initial(this);

                string ddfContent = File.ReadAllText(G_XSN_DDF.SavePath, Encoding.UTF8);
                StringBuilder packageFileNames = new StringBuilder();
                DirectoryInfo saveDirectoryInfo = new DirectoryInfo(saveFolder);

                foreach (FileInfo fileInfo in saveDirectoryInfo.GetFiles())
                {
                    packageFileNames.Append(fileInfo.Name + "\r\n");
                }

                using (FileStream fs = new FileStream(G_XSN_DDF.SavePath, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    StreamWriter sw = new StreamWriter(fs);
                    sw.Write(ddfContent + packageFileNames);
                    sw.Flush();
                }

                Process proc = new Process
                {
                    StartInfo = new ProcessStartInfo(Environment.SystemDirectory + @"\makecab.exe",
                        "/f " + SaveFolder + @"\package.ddf") { WorkingDirectory = SaveFolder }
                };
                proc.Start();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return true;
        }
    }
}